﻿using System;
using System.Collections.Generic;
using System.Linq;
using CanvasControl.Interface;

namespace CanvasControl.Model
{
    /// <summary>
    /// Модель холста рисования.
    /// </summary>
    public class CanvasModel
    {
        /// <summary>
        /// Множество этапов отрисовки.
        /// </summary>
        static readonly IEnumerable<PaintStages> STAGE_VALUES = Enum.GetValues(typeof(PaintStages)).Cast<PaintStages>().ToArray();

        /// <summary>
        /// Отображение из этапа отрисовки в список рисователей, вызывающихся на этом этапе.
        /// </summary>
        readonly Dictionary<PaintStages, List<IPainter>> painters = STAGE_VALUES.ToDictionary(s => s, s => new List<IPainter>());

        /// <summary>
        /// Список обработчиков состояний.
        /// </summary>
        readonly List<IInputListener> listeners = new List<IInputListener>();

        /// <summary>
        /// Модель области отображения.
        /// </summary>
        public ViewPortModel ViewPort { get; private set; }

        /// <summary>
        /// Создаёт новый экземпляр модели.
        /// </summary>
        public CanvasModel()
        {
            ViewPort = new ViewPortModel();
        }

        /// <summary>
        /// Добавляет рисователь в модель на определённый этап.
        /// </summary>
        /// <param name="stages">Этапы отрисовки.</param>
        /// <param name="painter">Рисователь.</param>
        public void AddPainter(PaintStages stages, IPainter painter)
        {
            foreach (var stage in STAGE_VALUES.Where(stage => stages.HasFlag(stage)))
                painters[stage].Add(painter);
        }

        /// <summary>
        /// Удаляет рисователь из модели.
        /// </summary>
        public void RemovePainter(IPainter painter)
        {
            foreach (var stage in STAGE_VALUES)
                painters[stage].Remove(painter);
        }

        /// <summary>
        /// Возвращает перечисление рисователей для конкретного этапа отрисовки.
        /// </summary>
        /// <param name="stage">Этап отрисовки.</param>
        public IEnumerable<IPainter> GetStagePainters(PaintStages stage)
        {
            return painters[stage];
        }

        public void Subscribe(IInputListener listener)
        {
            listeners.Add(listener);
        }

        public void Unsubscribe(IInputListener listener)
        {
            listeners.Remove(listener);
        }

        public IEnumerable<IInputListener> GetListeners()
        {
            return listeners;
        }
    }
}